'use client'

import { zodResolver } from '@hookform/resolvers/zod'
import {
	Button,
	Card,
	CardActions,
	CardContent,
	CircularProgress,
	Skeleton,
	Typography
} from '@mui/material'
import Grid from '@mui/material/Unstable_Grid2'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { Eraser, FilePen, FilePlus2, Pencil, Save, Trash } from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useCallback, useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'

import { ConfirmationDialog } from '@/components/dialogs/confirmation.dialog'
import { AutocompleteControlled } from '@/components/forms/AutocompleteControlled'
import { SelectFieldControlled } from '@/components/forms/SelectFieldControlled'
import { TextFieldControlled } from '@/components/forms/TextFieldControlled'

import type { IClient, IClients } from '@/types/client.types'
import {
	type IRequest,
	type IRequestForm,
	requestFormScheme,
	requestStatuses
} from '@/types/request.types'

import { DASHBOARD_PAGES } from '@/config/pages-url.config'

import { clientService } from '@/services/clients.service'
import { requestService } from '@/services/requests.service'

export function RequestCard({
	request_data,
	request_client,
	createMode
}: {
	request_data: IRequest | undefined
	request_client: IClient | undefined
	createMode?: boolean
}) {
	const queryClient = useQueryClient()
	const router = useRouter()

	const [request, setRequest] = useState<IRequest | undefined>(request_data)
	const [client, setClient] = useState<IClient | undefined>(request_client)
	const [editMode, setEditMode] = useState<boolean>(createMode ?? false)
	const [clientSearchOptions, setClientSearchOptions] = useState<
		{ name: string; id: number | null }[]
	>([])
	const [showDeleteConfDialog, setShowDeleteConfDialog] =
		useState<boolean>(false)

	useEffect(() => setClient(request_client), [request_client])

	const {
		formState: { errors, isDirty, isValid },
		handleSubmit,
		reset,
		control
	} = useForm<IRequestForm>({
		mode: 'onChange',
		resolver: zodResolver(requestFormScheme),
		defaultValues: request
	})

	useEffect(() => {
		setRequest(request_data)
		reset(request_data)
	}, [request_data])

	const updateRequest = useMutation({
		mutationKey: ['request', 'update', request?.id],
		mutationFn: (data: IRequestForm) =>
			requestService.update(request?.id!, data),
		onSuccess: data => {
			setEditMode(false)
			setRequest(data)
			queryClient.setQueryData(['request', data.id], data)
			queryClient.invalidateQueries({ queryKey: ['requests'] })
			if (client?.id !== data.client) {
				queryClient.invalidateQueries({
					queryKey: ['client', client ? client.id : null]
				})
			}
			reset(data)
			toast.success('Изменения сохранены')
		},
		onError: () => {
			toast.error('Ошибка сохранения')
		}
	})

	const createRequest = useMutation({
		mutationKey: ['request', 'create'],
		mutationFn: (data: IRequestForm) => requestService.create(data),
		onSuccess: data => {
			setRequest(data)
			reset(data)
			queryClient.invalidateQueries({ queryKey: ['requests'] })
			queryClient.setQueryData(['request', data.id], data)

			router.push(`${DASHBOARD_PAGES.REQUEST}${data.id}`)

			toast.success(`Заявка создана`, {
				description: `${data.first_name} #${data.id}`
			})
		},
		onError: () => {
			toast.error('Ошибка создания')
		}
	})

	const deleteRequest = useMutation({
		mutationKey: ['request', 'delete', request?.id],
		mutationFn: () => requestService.del(request?.id!),
		onSuccess: () => {
			queryClient.invalidateQueries({
				queryKey: ['request', request?.id]
			})
			queryClient.invalidateQueries({ queryKey: ['requests'] })

			router.back()
			toast.success('Заявка удалена', {
				description: `${request?.first_name} #${request?.id}`
			})
		}
	})

	const isPending =
		updateRequest.isPending ||
		deleteRequest.isPending ||
		createRequest.isPending

	const generateSearchResults = (data: IClients) => {
		setClientSearchOptions(
			data.results.map(client => ({
				name: `${client.first_name} ${client.last_name}`,
				id: client.id
			}))
		)
	}
	const searchClients = useMutation({
		mutationKey: ['search_clients'],
		mutationFn: (full_name: string) => clientService.fetchMany(full_name),
		onSuccess: data => generateSearchResults(data)
	})

	const enableEditMode = useCallback(
		() => !createMode && setEditMode(true),
		[createMode]
	)
	const declineEditMode = useCallback(() => {
		if (!createMode) setEditMode(false)
		reset(request)
	}, [request])

	const handleDelete = useCallback(() => {
		deleteRequest.mutate()
	}, [deleteRequest])

	const onSubmit = useCallback(
		(data: IRequestForm) =>
			createMode ? createRequest.mutate(data) : updateRequest.mutate(data),
		[createMode, createRequest, updateRequest]
	)

	return (
		<Card>
			<form noValidate>
				<CardContent>
					{!createMode && (
						<Typography
							sx={{ fontSize: 14 }}
							color='text.secondary'
							gutterBottom
						>
							{request ? (
								`Сервис: ${request.request_service.display_name}`
							) : (
								<Skeleton />
							)}
						</Typography>
					)}
					<Typography
						variant='h5'
						component='div'
					>
						{request ? (
							createMode ? (
								'Новая заявка'
							) : (
								`Заявка #${request.id}`
							)
						) : (
							<Skeleton />
						)}
					</Typography>
					{!createMode && (
						<Typography
							sx={{ mb: 1.5, display: 'flex' }}
							color='text.secondary'
						>
							<FilePlus2
								size={18}
								style={{ marginRight: 4 }}
							/>
							{request ? (
								request.created_on.format('HH:mm DD.MM.YYYY')
							) : (
								<Skeleton width={60} />
							)}
							;
							<FilePen
								size={18}
								style={{ marginRight: 4, marginLeft: 4 }}
							/>
							{request ? (
								request.updated_on.format('HH:mm DD.MM.YYYY')
							) : (
								<Skeleton width={60} />
							)}
						</Typography>
					)}
					{request ? (
						<Grid
							container
							spacing={3}
						>
							{!client && (
								<Grid xs={'auto'}>
									<TextFieldControlled
										control={control}
										name='first_name'
										label='Имя'
										copyBtn={true}
										onDoubleClick={enableEditMode}
									/>
								</Grid>
							)}

							<Grid xs={4}>
								<AutocompleteControlled
									control={control}
									callback={{
										mutate: searchClients.mutate,
										options: clientSearchOptions,
										isPending: searchClients.isPending,
										enabled: editMode
									}}
									defVal={{
										exists: request.client !== null,
										value: client && {
											id: client.id,
											name: `${client.first_name} ${client.last_name}`
										}
									}}
									readOnly={!editMode}
									disabled={isPending}
									onDoubleClick={enableEditMode}
									name='client'
									label='Клиент'
								/>
							</Grid>
							{errors['client'] && errors['client'].message}

							<Grid xs={'auto'}>
								<TextFieldControlled
									control={control}
									name='phone_number'
									label='Телефон'
									type='tel'
									copyBtn={true}
									disabled={isPending || client !== undefined}
									readOnly={!editMode}
									onDoubleClick={enableEditMode}
								/>
							</Grid>

							<Grid xs={4}>
								<TextFieldControlled
									control={control}
									name='number_in_program'
									label='Номер в ПО'
									readOnly={!editMode}
									disabled={isPending}
									onDoubleClick={enableEditMode}
									multiline
								/>
							</Grid>

							<Grid xs={'auto'}>
								<SelectFieldControlled
									control={control}
									name='status'
									label='Статус'
									options={Object.entries(requestStatuses).map(
										([key, value]) => ({
											id: Number(key),
											name: value
										})
									)}
									readOnly={!editMode}
									disabled={isPending}
									onDoubleClick={enableEditMode}
								/>
							</Grid>

							<Grid xs={6}>
								<TextFieldControlled
									control={control}
									name='note'
									label='Заметка'
									readOnly={!editMode}
									disabled={isPending}
									onDoubleClick={enableEditMode}
									multiline
								/>
							</Grid>

							<Grid xs={6}>
								<TextFieldControlled
									control={control}
									name='changes_history'
									label='История изменений'
									readOnly={!editMode}
									disabled={isPending}
									onDoubleClick={enableEditMode}
									multiline
								/>
							</Grid>
						</Grid>
					) : (
						<Skeleton
							variant='rectangular'
							height={300}
						/>
					)}
				</CardContent>
				<CardActions>
					{request && !createMode && (
						<ConfirmationDialog
							open={showDeleteConfDialog}
							title={'Вы уверены, что хотите УДАЛИТЬ эту ЗАЯВКУ?'}
							onConfirm={handleDelete}
							onClose={() => setShowDeleteConfDialog(false)}
						/>
					)}
					{request && !editMode && !createMode && (
						<>
							<Button
								size='small'
								startIcon={<Pencil size={20} />}
								onClick={enableEditMode}
							>
								Редактировать
							</Button>
							<Button
								size='small'
								color={'error'}
								startIcon={<Trash size={20} />}
								onClick={() => setShowDeleteConfDialog(true)}
								disabled={isPending}
							>
								Удалить
							</Button>
						</>
					)}
					{editMode && (
						<Button
							size='small'
							color={'success'}
							startIcon={<Save size={20} />}
							onClick={handleSubmit(onSubmit)}
							disabled={isPending || !isDirty || !isValid}
						>
							Сохранить
						</Button>
					)}
					{editMode && (
						<Button
							size='small'
							color={'error'}
							startIcon={<Eraser size={20} />}
							onClick={declineEditMode}
							disabled={isPending}
						>
							{createMode ? 'Очистить' : 'Отменить'}
						</Button>
					)}
					{isPending && <CircularProgress size={20} />}
				</CardActions>
			</form>
		</Card>
	)
}
